package com.feng.profile.service;

import com.feng.common.enums.AlgorithmEnum;
import com.feng.common.exception.ErrorCode;
import com.feng.common.exception.ValidationException;
import com.feng.common.util.MD5Util;
import com.feng.profile.model.entity.QSysUser;
import com.feng.profile.model.entity.SysUser;
import com.feng.profile.model.enums.StatusEnum;
import com.feng.profile.vo.LoginVo;
import com.feng.profile.vo.UserAddReq;
import com.feng.profile.vo.UserInfo;
import com.querydsl.jpa.impl.JPAQueryFactory;
import org.apache.shiro.SecurityUtils;
import org.apache.shiro.authc.AuthenticationException;
import org.apache.shiro.authc.UsernamePasswordToken;
import org.apache.shiro.crypto.hash.SimpleHash;
import org.apache.shiro.subject.Subject;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.BeanUtils;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.CollectionUtils;

import javax.persistence.EntityManager;
import javax.persistence.PersistenceContext;
import java.util.Date;
import java.util.List;

/**
 * @author Lee
 */
@Service
public class ProfileUserService {

    private final Logger LOGGER = LoggerFactory.getLogger(ProfileUserService.class);

    @PersistenceContext
    private EntityManager em;

    public UserInfo login(LoginVo loginVo) throws ValidationException {
        QSysUser qSysUser = QSysUser.sysUser;
        Subject subject = SecurityUtils.getSubject();
        if (!subject.isAuthenticated()) {
            UsernamePasswordToken token = new UsernamePasswordToken(loginVo.getUserName(), loginVo.getPassword());
            token.setRememberMe(true);
            try {
                subject.login(token);
            } catch (AuthenticationException e) {
                LOGGER.info("登录失败,失败原因：{}",e.getMessage());
                throw new ValidationException(ErrorCode.CheckError,"登录失败,失败原因："+e.getMessage());
            }
        }
        SysUser user = null;
        try {
            user = new JPAQueryFactory(em)
                    .select(qSysUser)
                    .from(qSysUser)
                    .where(qSysUser.userName.eq(loginVo.getUserName())).fetchOne();
        } catch (Exception e) {
            LOGGER.error("登录成功，但查询不到用户信息");
            throw new ValidationException(ErrorCode.CheckError,"查询不到用户信息");
        }
        UserInfo userInfo = new UserInfo();
        BeanUtils.copyProperties(user,userInfo);
        return userInfo;
    }

    @Transactional
    public void addSysUser(UserAddReq userAddReq) throws ValidationException{
        String pwdReg = "[.*\\d+]{4,16}";  // 密码匹配为包含数字的4-16位数字字符串
        String password = userAddReq.getPassword();
        if (!password.matches(pwdReg)) {
            LOGGER.info("密码不满足规则");
            throw new ValidationException(ErrorCode.ValidationError,"密码不满足规则");
        }
        QSysUser qSysUser = QSysUser.sysUser;
        List<String> userNames = new JPAQueryFactory(em)
                .select(qSysUser.userName)
                .from(qSysUser)
                .where(qSysUser.userName.eq(userAddReq.getUserName()))
                .fetch();
        if (!CollectionUtils.isEmpty(userNames)) {
            LOGGER.info("用户名已经存在");
            throw new ValidationException(ErrorCode.CheckError,"用户名已经存在");
        }
        SimpleHash credentials = MD5Util.toMd5(AlgorithmEnum.MD5, password, userAddReq.getUserName());

        SysUser sysUser = new SysUser();
        BeanUtils.copyProperties(userAddReq,sysUser);
        sysUser.setPassword(credentials.toString());
        sysUser.fillDefaultValues();
        sysUser.setCreateTime(new Date());
        sysUser.setStatus(StatusEnum.E);
        try {
            em.persist(sysUser);
        } catch (Exception e) {
            LOGGER.info("用户添加失败,parameter：{}", sysUser);
            throw new ValidationException(ErrorCode.Other, "用户添加失败");
        }
    }

}
